home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 2 / Apprentice-Release2.iso / Source Code / C++ / Applications / Nuntius 1.2 / src / Nuntius / UGroupViewCmds.cp < prev    next >
Encoding:
Text File  |  1994-02-20  |  17.3 KB  |  730 lines  |  [TEXT/MPS ]

  1. // Copyright © 1992 Peter Speck, speck@dat.ruc.dk. All rights reserved.
  2. // UGroupViewCmds.cp
  3.  
  4. #include "UGroupViewCmds.h"
  5. #include "UGroupTreeDoc.h"
  6. #include "UGroupTree.h"
  7. #include "UGroupTreeView.h"
  8. #include "UGroupList.h"
  9. #include "UGroupListView.h"
  10. #include "UNewsAppl.h"
  11. #include "UGroupDoc.h"
  12. #include "UGroupListDoc.h"
  13. #include "Tools.h"
  14. #include "ViewTools.h"
  15.  
  16. #include <RsrcGlobals.h>
  17. #include <ErrorGlobals.h>
  18. #include <ToolUtils.h>
  19. #include <Packages.h>
  20.  
  21. #pragma segment MyGroupList
  22.  
  23. #define qDebugGroupDrag qDebug & 0
  24.  
  25. #define qDebugTreeKey qDebug & 0
  26. #define qDebugTreeKeyVerbose qDebugTreeKey
  27.  
  28. //========================================================================
  29. TGroupTracker::TGroupTracker()
  30. {
  31. }
  32.  
  33.  
  34. pascal void TGroupTracker::Initialize()
  35. {
  36.     inherited::Initialize();
  37.     fDoesDragGray = false;
  38.     fHasDrawedOnDesktop = false;
  39.     fCurrentGrayPos = CPoint(0,0);
  40.     fGrayPictH = nil;
  41.     fMouseOffsetInGrayPict = CPoint(0, 0);
  42.     fHasDrawedInsertMark = false;
  43.     fOldInsertMarkRect = VRect(0, 0, 0, 0);
  44.     fHitGroupListView = nil;
  45.     fHitGroupList = nil;
  46.     fDraggedGroups = nil;
  47.     fMakingCopy = false;
  48.     fInsertBeforeName = "";
  49. }
  50.  
  51. pascal void TGroupTracker::IGroupTracker(
  52.                                                 CommandNumber itsCommandNumber,
  53.                                                 const VPoint &itsMouse,
  54.                                                 Boolean makingCopy)
  55. {
  56.     this->ITracker(itsCommandNumber, nil, kCantUndo, kDoesNotCauseChange, NULL, 
  57.                     nil, nil, itsMouse);
  58.     fMakingCopy = makingCopy;
  59. #if qDebugGroupDrag
  60.     if (fMakingCopy)
  61.         fprintf(stderr, "fMakingCopy = %hd\n", qDebugGroupDrag);
  62. #endif
  63. }
  64.  
  65. pascal void TGroupTracker::Free()
  66. {
  67. #if qDebugGroupDrag
  68.     fprintf(stderr, "TGroupTracker::Free, done tracking\n");
  69. #endif
  70.     DisposeIfHandle(Handle(fGrayPictH)); fGrayPictH = nil;
  71.     FreeIfObject(fDraggedGroups); fDraggedGroups = nil;
  72.     inherited::Free();
  73. }
  74.  
  75. pascal void TGroupTracker::DoIt()
  76. {
  77. }
  78.  
  79. pascal void TGroupTracker::DoFocus()
  80. {
  81.     inherited::DoFocus();
  82.     if (fDeskTopTrackingPort)
  83.         SetPort(fDeskTopTrackingPort);
  84. }
  85.  
  86. pascal void TGroupTracker::TrackConstrain(TrackPhase /* aTrackPhase */,
  87.                                         const VPoint& /* anchorPoint */,
  88.                                       const VPoint& /* previousPoint */,
  89.                                     VPoint& /* nextPoint */,
  90.                                         Boolean /* mouseDidMove */)
  91. {
  92.     // don't constrain anything!
  93. }
  94.  
  95. pascal void TGroupTracker::ConstrainOnce(Boolean /* didMouseMove */)
  96. {
  97.     // don't constrain anything!
  98. }
  99.  
  100.  
  101. pascal void TGroupTracker::TrackFeedback(TrackPhase /* aTrackPhase */,
  102.                                         const VPoint& /* anchorPoint */,
  103.                                         const VPoint& /* previousPoint */,
  104.                                         const VPoint& /* nextPoint */,
  105.                                         Boolean /* mouseDidMove */,
  106.                                         Boolean /* turnItOn */)
  107. {
  108. }
  109.  
  110. pascal TTracker *TGroupTracker::TrackMouse(TrackPhase aTrackPhase,
  111.                                              VPoint &anchorPoint,
  112.                                              VPoint &previousPoint,
  113.                                              VPoint &nextPoint,
  114.                                              Boolean /* mouseDidMove */) // override 
  115. {
  116. // da der blev specificeret nil som view til ITracker, er coordinaterne globale!
  117. #if qDebugGroupDrag & 0
  118.     GrafPtr gp;
  119.     GetPort(gp);
  120.     fprintf(stderr, "At TrackMouse: GrafPtr: $%lx\n", long(gp));
  121. #endif
  122. #if qDebugGroupDrag & 0
  123.     fprintf(stderr, "aTrackPhase = %hd, ", short(aTrackPhase));
  124.     fprintf(stderr, "anc = %s, ", (char*)anchorPoint);
  125.     fprintf(stderr, "prev = %s, ", (char*)previousPoint);
  126.     fprintf(stderr, "next = %s\n", (char*)nextPoint);
  127. #endif
  128.     VPoint diff;
  129.     if (!fDoesDragGray)
  130.     {
  131.         diff = nextPoint - anchorPoint;
  132. #if qDebugGroupDrag & 0
  133.         fprintf(stderr, "TGroupTracker::TrackMouse, non-gray diff: %s\n", (char*)diff);
  134. #endif
  135.         if (diff.v > -3 && diff.v < 3 && diff.h > -3 && diff.h < 3)
  136.         {
  137.             if (aTrackPhase == trackEnd)
  138.                 return nil;
  139.             else
  140.                 return this;
  141.         }
  142.         StartGrayDrag();
  143.         fCurrentGrayPos = CPoint(0, 0);
  144.         diff = nextPoint;
  145.     }
  146.     else
  147.     {
  148.         diff = nextPoint - previousPoint;
  149.     }
  150.  
  151.     if (diff != VPoint(0, 0))
  152.     {
  153.         if (fHasDrawedOnDesktop)
  154.             DrawGray();
  155.         fCurrentGrayPos += diff.ToPoint();
  156.     }
  157.  
  158.     TestForHit(nextPoint.ToPoint());
  159.  
  160.     if (diff != VPoint(0, 0) || !fHasDrawedOnDesktop)
  161.         DrawGray();
  162.     
  163.     if (aTrackPhase != trackEnd)
  164.         return this;
  165.  
  166.     if (fHasDrawedOnDesktop)
  167.         DrawGray(); // remove it
  168.     if (fHasDrawedInsertMark)
  169.         DrawInsertMark(); // remove it
  170.  
  171.     if (fHitGroupListView)
  172.         DragToGroupList();
  173.     else
  174.         DidNotHitWindow();
  175.         
  176.     return nil; // no more tacking
  177. }
  178.  
  179. short MyAbs(short a)
  180. {
  181.     return a < 0 ? -a : a;
  182. }
  183.  
  184. void TGroupTracker::DidNotHitWindow()
  185. {
  186.     if (fHasDrawedOnDesktop)
  187.         DrawGray();
  188.     CPoint diff( (fNextPoint - fAnchorPoint).ToPoint() );
  189.     short dh = MyAbs(diff.h);
  190.     short dv = MyAbs(diff.v);
  191.     short noSteps = 1 + short(Min(6, (dh + dv) / 8));
  192. #if qDebugGroupDrag
  193.     fprintf(stderr, "TGroupTracker::DidNotHitWindow, does animation with %hd steps\n", noSteps);
  194. #endif
  195.     CPoint delta;
  196.     delta.h = -diff.h / noSteps;
  197.     delta.v = -diff.v / noSteps;
  198.     for (long i = 0; i < noSteps; i++)
  199.     {
  200.         fCurrentGrayPos += delta;
  201.         DrawGray();
  202.         long li;
  203.         Delay(1, li);
  204.         DrawGray();
  205.     }
  206. }
  207.  
  208. void TGroupTracker::StartGrayDrag()
  209. {
  210. #if qDebugGroupDrag
  211.     fprintf(stderr, "TGroupTracker::StartGrayDrag, Starts gray drag\n");
  212. #endif
  213.     fCurrentGrayPos = CPoint(0, 0);
  214.     MakeGrayPict();
  215.     DoFocus();
  216.     CopyRgn(GetGrayRgn(), fDeskTopTrackingPort->clipRgn);
  217.     fDoesDragGray = true;
  218. }
  219.  
  220. void TGroupTracker::DrawGray()
  221. {
  222. #if qDebug
  223.     if (!fGrayPictH)
  224.         ProgramBreak("DrawGray called when fGrayPictH == nil");
  225. #endif
  226.     DoFocus();
  227. #if qDebugGroupDrag & 0
  228.     GrafPtr gp;
  229.     GetPort(gp);
  230.     fprintf(stderr, "At DrawGray: GrafPtr: $%lx\n", long(gp));
  231. #endif
  232.     CRect r( (**fGrayPictH).picFrame );
  233.     r -= r[topLeft];
  234.     r -= fMouseOffsetInGrayPict;
  235.     r += fCurrentGrayPos;
  236.     DrawPicture(fGrayPictH, r);
  237.     fHasDrawedOnDesktop = !fHasDrawedOnDesktop;
  238. }
  239.  
  240. Boolean TGroupTracker::CalcNewHit(VPoint globalMouse, TGroupListView *&groupListView, 
  241.                                                                     VRect &newMarkRect, VPoint &localMouse)
  242. {
  243.     groupListView = nil;
  244.     WindowPtr theWindowP;
  245.     short part = FindWindow(globalMouse.ToPoint(), theWindowP);
  246.     TWindow *window = WMgrToWindow(theWindowP);
  247.     if (!window)
  248.         return false;
  249. #if qDebug
  250.     if (!IsObject(window))
  251.         ProgramBreak("Got bogous window from WMgrToWindow");
  252. #endif
  253.     if (!window->fDocument)
  254.         return false; // document had no window, so not a GroupListWindow
  255. #if qDebug
  256.     if (!IsObject(window->fDocument))
  257.         ProgramBreak("Window has bogous document");
  258. #endif
  259.     if (window->fDocument->fIdentifier != kGroupListDocFileType)
  260.         return false; // not a GroupListWindow
  261.     TGroupListDoc *doc = (TGroupListDoc*) window->fDocument;    
  262.     groupListView = doc->GetGroupListView();
  263. #if qDebug
  264.     if (!IsObject(groupListView))
  265.         ProgramBreak("TGroupListDoc returned bogous TGroupListView");
  266. #endif
  267.     localMouse = globalMouse - window->fLocation;
  268. #if qDebugGroupDrag & 0
  269.     fprintf(stderr, "TGroupTracker::CalcNewHit, localWindowPos = %s", (char*)localMouse);
  270. #endif
  271.     groupListView->Focus();
  272.     groupListView->WindowToLocal(localMouse);
  273.  
  274. #if qDebugGroupDrag & 0
  275.     fprintf(stderr, ", localGridViewPos = %s", (char*)localMouse);
  276.     fprintf(stderr, ", GV.fSize = %s\n", (char*)VPoint(groupListView->fSize));
  277. #endif
  278.     VPoint localPos(localMouse);
  279.     localPos.h = 1;
  280.     localPos.v += groupListView->fGridViewTextStyle.fRowHeight / 2;
  281.     short insertBeforeRow;
  282.     if (localPos.v < 0)
  283.         insertBeforeRow = 1;
  284.     else if (localPos.v >= groupListView->fSize.v)
  285.         insertBeforeRow = groupListView->fNumOfRows + 1;
  286.     else
  287.     {
  288.         GridCell cell = groupListView->VPointToCell(localPos);
  289.         insertBeforeRow = cell.v;
  290. #if qDebug
  291.         if (insertBeforeRow == 0)
  292.             fprintf(stderr, "TGroupTracker::CalcNewHit, insertBeforeRow == 0 in GridViewHit\n");
  293. #endif
  294.     }
  295. #if qDebugGroupDrag & 0
  296.     fprintf(stderr, "-  insertBeforeRow = %hd", insertBeforeRow);
  297. #endif
  298.     CStr255 s;
  299.     GetBeforeGroupName(groupListView, insertBeforeRow, s);
  300.     fInsertBeforeName = s;
  301.     const kHitRectHeight = 1;
  302.     newMarkRect.left = 0;
  303.     newMarkRect.top = (insertBeforeRow - 1) * groupListView->fGridViewTextStyle.fRowHeight;
  304.     newMarkRect.right = groupListView->fSize.h;
  305.     newMarkRect.bottom = newMarkRect.top + kHitRectHeight;
  306.     return true;
  307. }
  308.  
  309. void TGroupTracker::GetBeforeGroupName(TGroupListView *groupListView, short beforeRow, CStr255 &name)
  310. {
  311.     if (beforeRow > groupListView->fNumOfRows)
  312.         name = "";
  313.     else
  314.         groupListView->GetGroupList()->GetGroupAt(beforeRow, name);
  315. }
  316.  
  317. void TGroupTracker::DrawInsertMark()
  318. {
  319.     DoFocus();
  320.     PenNormal();
  321.     VRect markRect(fOldInsertMarkRect);
  322.     fHitGroupListView->LocalToSuperVRect(markRect);
  323.     fHitGroupListView->fSuperView->Focus();
  324.     CRect r(markRect.ToRect());
  325.     PenMode(patXor);
  326.     PenPat(&qd.ltGray);
  327.     PaintRect(r);
  328.     PenNormal();
  329.     fHasDrawedInsertMark = !fHasDrawedInsertMark;
  330. }
  331.  
  332. void TGroupTracker::TestForHit(VPoint globalMouse)
  333. {
  334. /*
  335. havde    nyt    forskellig
  336. ja       ja      ja         g + n
  337. ja       ja      nej                -
  338. ja       nej     ?          g
  339. nej      nej     ?          -
  340. nej      ja      ?          n
  341. */
  342.     Boolean hadOld = fHasDrawedInsertMark;
  343.     VRect newMarkRect(0, 0, 0, 0);
  344.     TGroupListView *groupListView = nil;
  345.     VPoint localMouse;
  346.     Boolean gotRect = CalcNewHit(globalMouse, groupListView, newMarkRect, localMouse);
  347.  
  348.     Boolean needsToScroll = false;
  349.     VPoint delta;
  350.     if (gotRect)
  351.     {
  352.         groupListView->GetScroller(true)->AutoScroll(localMouse, delta);
  353.         needsToScroll = (delta.v != 0);
  354.     }
  355.  
  356.     Boolean isNewRect = needsToScroll || (newMarkRect != fOldInsertMarkRect);
  357.  
  358.     Boolean removeOld = hadOld  && (!gotRect || isNewRect);
  359.     Boolean drawNew   = gotRect && (!hadOld  || isNewRect);
  360.  
  361. #if qDebug
  362.     if (hadOld && !IsObject(fHitGroupListView))
  363.         ProgramBreak("Had old and fHitGroupListView is not object");
  364.     if (gotRect && !IsObject(groupListView))
  365.         ProgramBreak("gotRect && groupListView is not object");
  366. #endif
  367. #if qDebugGroupDrag & 0
  368.     fprintf(stderr, "%s", (char*)VRect(fOldInsertMarkRect));
  369.     fprintf(stderr, " -> %s", (char*)newMarkRect);
  370.     fprintf(stderr, ", hadOld = %hd, got = %hd, isNew = %hd", hadOld, gotRect, isNewRect);
  371.     fprintf(stderr, ", -Old = %hd, +New = %hd\n", removeOld, drawNew);
  372. #endif
  373.  
  374.     
  375.     if (removeOld)
  376.     {
  377.         DrawInsertMark();
  378.         fHasDrawedInsertMark = false;
  379.     }
  380.  
  381.     if (needsToScroll)
  382.     {
  383.         if (fHasDrawedOnDesktop)
  384.             DrawGray();
  385.         groupListView->GetScroller(true)->ScrollBy(VPoint(0, delta.v), kRedraw);
  386.         groupListView->GetWindow()->Focus();
  387.         groupListView->GetWindow()->Update();
  388.     }
  389.  
  390.     if (drawNew)
  391.     {
  392.         fOldInsertMarkRect = newMarkRect;
  393.         fHitGroupListView = groupListView;
  394.         fHitGroupList = fHitGroupListView->GetGroupList();;
  395.         DrawInsertMark();
  396.         fHasDrawedInsertMark = true;
  397.     }
  398.     
  399.     if (!gotRect)
  400.     {
  401.         fHitGroupListView = nil;
  402.         fHitGroupList = nil;
  403.     }
  404. }
  405.  
  406. void TGroupTracker::CreateListOfDraggedGroups()
  407. {
  408.     Failure(minErr, 0);
  409. }
  410.  
  411. void TGroupTracker::CheckForExistingGroups(TGroupListView *hitGroupListView, Boolean makingCopy)
  412. {
  413.     if (hitGroupListView->GetGroupList()->HasOneOfTheGroupsInList(fDraggedGroups))
  414.     {
  415.         short index = makingCopy ? kCopyGroupsWordIndex : kMoveGroupsWordIndex;
  416.         CStr255 moveCopyText;
  417.         MyGetIndString(moveCopyText, index);
  418.         ParamText(gEmptyString, gEmptyString, gEmptyString, moveCopyText);
  419.         if (MacAppAlert(kOverwriteExistingGroupsAlert, nil) != ok)
  420.             Failure(0, 0);
  421.     }
  422. }
  423.  
  424. void TGroupTracker::DragToGroupList()
  425. {
  426.     CreateListOfDraggedGroups();
  427.     if (fDraggedGroups->GetSize() > 25)
  428.     {
  429.         CStr255 s;
  430.         NumToString(fDraggedGroups->GetSize(), s);
  431.         ParamText(gEmptyString, gEmptyString, gEmptyString, s);
  432.         if (MacAppAlert(phSubscribeVeryManyGroups, nil) != ok)
  433.             Failure(0, 0);
  434.     }
  435. #if qDebug
  436.     if (!IsObject(fHitGroupListView))
  437.         ProgramBreak("fHitGroupListView is not object");
  438.     if (!IsObject(fDraggedGroups))
  439.         ProgramBreak("fDraggedGroups is not object");
  440. #endif
  441.     CheckForExistingGroups(fHitGroupListView, fMakingCopy);
  442.     fHitGroupListView->DeleteGroupsFromList(fDraggedGroups);
  443.  
  444.     ArrayIndex index;
  445.     if (fInsertBeforeName == "")
  446.         index = fHitGroupList->GetSize() + 1;
  447.     else
  448.         index = fHitGroupList->FindIndexFromName(CStr255(fInsertBeforeName));
  449.     if (index == kEmptyIndex)
  450.     {
  451. #if qDebug
  452.         ProgramBreak("before index is kEmptyIndex");
  453. #endif
  454.         index = 1;
  455.     }
  456.     fHitGroupListView->AddGroupsFromListBefore(index, fDraggedGroups);
  457. }
  458.  
  459. void TGroupTracker::MakeGrayPict()
  460. {
  461.     Failure(minErr, 0);
  462. }
  463.  
  464. void TGroupTracker::WasDraggedToGroupTree() //@@ not called yet
  465. {
  466.     gApplication->Beep(2);
  467. }
  468. //========================================================================
  469. //========================================================================
  470. TGroupViewKeyCommand::TGroupViewKeyCommand()
  471. {
  472. }
  473.  
  474.  
  475. pascal void TGroupViewKeyCommand::Initialize()
  476. {
  477.     inherited::Initialize();
  478.     fGridView = nil;
  479. }
  480.  
  481. void TGroupViewKeyCommand::IGroupViewKeyCommand(TGridView *gv)
  482. {
  483.     inherited::ICommand(cGenericCommand, nil, false, false, nil);
  484.     fGridView = gv;
  485. #if qDebug
  486.     if (!IsObject(fGridView))
  487.         ProgramBreak("fGridView is not object");
  488. #endif
  489. }
  490.  
  491. pascal void TGroupViewKeyCommand::Free()
  492. {
  493.     fGridView = nil;
  494.     inherited::Free();
  495. }
  496.  
  497. pascal void TGroupViewKeyCommand::DoIt()
  498. {
  499.     if (fGridView->fNumOfRows)
  500.     {
  501.         SetUp();
  502.         DoAllLines();
  503.         SetDown();
  504.     }
  505.     fGridView->ScrollSelectionIntoView(kRedraw);
  506. }
  507.  
  508. void TGroupViewKeyCommand::SetUp()
  509. {
  510.     fCandidateName = "";
  511.     fCandidateLine = kEmptyIndex;
  512.     fLastLine = fGridView->fNumOfRows;
  513.     if (fGridView->IsAnyCellSelected())
  514.     {
  515.         fCurrentSelectedLine = fGridView->FirstSelectedCell().v;
  516.         CStr255 s;
  517.         GetLineText(fCurrentSelectedLine, s);
  518.         fCurrentSelectedName = s;
  519.     }
  520.     else
  521.     {
  522.         fCurrentSelectedName = "";
  523.         fCurrentSelectedLine = kEmptyIndex;
  524.     }
  525. }
  526.  
  527. void TGroupViewKeyCommand::SetDown()
  528. {
  529.     if (fCandidateLine == kEmptyIndex)
  530.         HandleNoFound();
  531.     if (fCandidateLine != kEmptyIndex)
  532.     {
  533.         GridCell cell(GridCell(1, short(fCandidateLine)));
  534.         fGridView->SelectCell(cell, false, true, true);
  535.     }
  536. }
  537.  
  538. void TGroupViewKeyCommand::DoAllLines()
  539. {
  540.     for (ArrayIndex line = 1; line <= fLastLine; line++)
  541.         DoOneLine(line);
  542. }
  543.  
  544. void TGroupViewKeyCommand::DoOneLine(ArrayIndex line)
  545. {
  546.     CStr255 text;
  547.     GetLineText(line, text);
  548.     DoLine(line, text);
  549. }
  550.  
  551. void TGroupViewKeyCommand::GetLineText(ArrayIndex /* line */, CStr255 & /* text */)
  552. {
  553.     SubClassResponsibility();
  554. }
  555.  
  556. void TGroupViewKeyCommand::DoLine(ArrayIndex /* line */, const CStr255 & /* text */)
  557. {
  558.     SubClassResponsibility();
  559. }
  560.  
  561. void TGroupViewKeyCommand::HandleNoFound()
  562. {
  563. }
  564.  
  565. //--------------------------------------------------------------------------------
  566. TGroupViewTypeNameCommand::TGroupViewTypeNameCommand()
  567. {
  568. }
  569.  
  570.  
  571. pascal void TGroupViewTypeNameCommand::Initialize()
  572. {
  573.     inherited::Initialize();
  574.     fLastTick = 0;
  575.     fTypeChars = "";
  576.     fChar = 32;
  577. }
  578.  
  579. void TGroupViewTypeNameCommand::IGroupViewTypeNameCommand(TGridView *gv, TToolboxEvent *event)
  580. {
  581.     inherited::IGroupViewKeyCommand(gv);
  582.     fChar = event->fCharacter;
  583.     fCharTick = event->fEventRecord.when;
  584. }
  585.  
  586. pascal void TGroupViewTypeNameCommand::Free()
  587. {
  588.     inherited::Free();
  589. }
  590.  
  591. void TGroupViewTypeNameCommand::SetUp()
  592. {
  593.     inherited::SetUp();
  594.     if (fCharTick - fLastTick > kKeyTimeout)
  595.     {
  596.         fTypeChars = "";
  597. #if qDebugTreeKey
  598.         fprintf(stderr, "TypeName: timeout for old name\n");
  599. #endif
  600.     }
  601.     fTypeChars += fChar;
  602. #if qDebugTreeKey
  603.     fprintf(stderr, "TypeName: Current typed chars: '%s'\n", (char*)fTypeChars);
  604. #endif
  605. }
  606.  
  607. void TGroupViewTypeNameCommand::SetDown()
  608. {
  609.     inherited::SetDown();
  610.     fLastTick = fCharTick;
  611. }
  612.  
  613. void TGroupViewTypeNameCommand::DoLine(ArrayIndex line, const CStr255 &text)
  614. {
  615. #if qDebugTreeKeyVerbose
  616.     fprintf(stderr, "TGroupListTypeNameCommand::DoLine, line = %hd, text = '%s'\n", line, (char*)text);
  617. #endif
  618.     if (text < fTypeChars)
  619.     {
  620. #if qDebugTreeKeyVerbose
  621.         fprintf(stderr, "-  text < fTypeChars\n");
  622. #endif
  623.         return;
  624.     }
  625.     if (text < fCandidateName || !fCandidateName.Length())
  626.     {
  627. #if qDebugTreeKey
  628.         fprintf(stderr, "TGroupListTypeNameCommand: Found new candidate: '%s'\n", (char*)text);
  629. #endif
  630.         fCandidateName = text;
  631.         fCandidateLine = line;
  632.     }
  633. }
  634.  
  635.  
  636. void TGroupViewTypeNameCommand::HandleNoFound()
  637. {
  638.     inherited::HandleNoFound();
  639.     fCandidateLine = fLastLine;
  640. #if qDebugTreeKey
  641.     fprintf(stderr, "TGroupListTypeNameCommand: Found no candidate, selects last cell\n");
  642. #endif
  643. }
  644.  
  645. //-------------------------------------------------------------
  646. TGroupViewTabKeyCommand::TGroupViewTabKeyCommand()
  647. {
  648. }
  649.  
  650.  
  651. pascal void TGroupViewTabKeyCommand::Initialize()
  652. {
  653.     inherited::Initialize();
  654.     fFirstLastLine = kEmptyIndex;
  655. }
  656.  
  657. void TGroupViewTabKeyCommand::IGroupViewTabKeyCommand(TGridView *gv, Boolean forward)
  658. {
  659.     inherited::IGroupViewKeyCommand(gv);
  660.     fForward = forward;
  661. }
  662.  
  663. pascal void TGroupViewTabKeyCommand::Free()
  664. {
  665.     inherited::Free();
  666. }
  667.  
  668. void TGroupViewTabKeyCommand::DoLine(ArrayIndex line, const CStr255 &text)
  669. {
  670.     if (fForward)
  671.         DoForwardLine(line, text);
  672.     else
  673.         DoBackwardLine(line, text);
  674. }
  675.  
  676. void TGroupViewTabKeyCommand::DoForwardLine(ArrayIndex line, const CStr255 &text)
  677. {
  678. #if qDebugTreeKeyVerbose
  679.     fprintf(stderr, "TGroupViewTabKeyCommand::DoLine, line = %hd, text = '%s'\n", line, (char*)text);
  680. #endif
  681.     Boolean isLarger;
  682.     if (line <= fCurrentSelectedLine)
  683.         isLarger = text > fCurrentSelectedName;
  684.     else
  685.         isLarger = text >= fCurrentSelectedName;
  686.     Boolean gotNew = isLarger && (text < fCandidateName || !fCandidateName.Length());
  687.     if (gotNew)
  688.     {
  689.         fCandidateName = text;
  690.         fCandidateLine = line;
  691.     }
  692.     if (fFirstLastLine == kEmptyIndex || text < fFirstLastName)
  693.     {
  694.         fFirstLastName = text;
  695.         fFirstLastLine = line;
  696.     }
  697. }
  698.  
  699. void TGroupViewTabKeyCommand::DoBackwardLine(ArrayIndex line, const CStr255 &text)
  700. {
  701.     Boolean isSmaller;
  702.     if (line < fCurrentSelectedLine)
  703.         isSmaller = text <= fCurrentSelectedName;
  704.     else
  705.         isSmaller = text < fCurrentSelectedName;
  706.     Boolean gotNew;
  707.     if (line < fCurrentSelectedLine)
  708.         gotNew = isSmaller && (text >= fCandidateName || !fCandidateName.Length());
  709.     else
  710.         gotNew = isSmaller && (text >  fCandidateName || !fCandidateName.Length());
  711.     if (gotNew)
  712.     {
  713.         fCandidateName = text;
  714.         fCandidateLine = line;
  715.     }
  716.     if (fFirstLastLine == kEmptyIndex || text > fFirstLastName)
  717.     {
  718.         fFirstLastName = text;
  719.         fFirstLastLine = line;
  720.     }
  721. }
  722.  
  723. void TGroupViewTabKeyCommand::HandleNoFound()
  724. {
  725.     fCandidateLine = fFirstLastLine;
  726. #if qDebugTreeKey
  727.     fprintf(stderr, "TGroupViewTabKeyCommand: Found no candidate, selects first/last cell\n");
  728. #endif
  729. }
  730.